package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 面向切面编程
 */
//@Component //让spring创建该类的对象，保存到IOC容器中
 //@Aspect  //表示该类是一个切面类，对目标方法进行增强
@Slf4j
public class TimeAspect2 {

//    //前置通知，在目标方法执行之前执行
//    @Before("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
//    public void before(){
//        log.info("前置通知before");
//    }
//
//    //后置通知/返回后通知，在目标方法执行之后且不出现异常时执行
//    @AfterReturning("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
//    public void afterReturning(){
//        log.info("后置通知afterReturning");
//    }
//
//    //异常通知，在目标方法执行之后且出现异常时执行
//    @AfterThrowing("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
//    public void afterThrowing(){
//        log.info("异常通知afterThrowing");
//    }
//
//    //最终通知，在目标方法执行之后无论是否出现异常都执行
//    @After("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
//    public void after(){
//        log.info("最终通知after");
//    }


    /**
     * @Around 环绕通知
     * @Around("")：写在方法上，表示该方法是一个通知方法，在方法内定义通知（要增强的逻辑代码）内容
     * execution(* com.itheima.service.impl.DeptServiceImpl.*(..)) :切点表达式，找出哪些类的哪些方法要增强，找切点。
     *  * ：任意一个返回值类型、任意一个包名、类名、方法名、任意一个参数类型
     *  .. ：表示任意多个任意类型的参数
     *
     * @param pjp
     * @return
     */
    @Around("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {
        Object result = null;   //返回值表示调用list()、add()、delete()等方法的返回值
        try {
            //1 获取开始时间
            log.info("前增强---前置通知");
            //2 执行目标对象方法
            result = pjp.proceed();
            //3 获取结束时间，计算耗时并打印   京都念慈菴川贝枇杷膏
            log.info("后增强---后置通知");
        } catch (Throwable e) {
            e.printStackTrace();
            log.info("异常通知");
        } finally {
            log.info("最终通知");
        }

        return result;
    }
}
